﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EtlComm;
using ETLHandler;
using System.Collections;
using System.Threading;
using System.Xml.Linq;
using System.Net.NetworkInformation;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;

namespace ETLDispatcher
{
    public class EtlDispatcher : IEDTDispatcher
    {
        #region 辅助完成任务状态序列化
        [Serializable]
        class TaskStatus
        {
            public int TaskID;
            public StepType ParamType;
            public uint Executions;
            public Queue<object> TaskQueue;
        }
        [Serializable]
        class StationStatus
        {
            public string StationID;
            public IList<TaskStatus> TaskList;
        }
        #endregion

        public ServiceBaseLog log { set; get; }
        /// <summary>
        /// 是否激活
        /// </summary>
        public bool Active { set; get; }

        #region 私有变量
        //信号量
        //Semaphore sem = new Semaphore(20, 10000);
        //配置文件
        SynXML synxml;
        //加油站列表
        IList<StationObject> lstStaObj;
        //每日更新用的内核事件
        AutoResetEvent arEvent = new AutoResetEvent(false);
        //用于阻止任务，进行更新时用
        ManualResetEvent mrEvent = new ManualResetEvent(false);
        //状态保存计数
        uint loopCount = 0;
        //时间监视
        //Timer timeMonitorTimer = null;
        //调度线程
        Timer KillTimer = null;
        #endregion


        /// <summary>
        /// 构造函数
        /// </summary>
        public EtlDispatcher()
        {
            synxml = new SynXML();
            synxml.OnUpdateLog += new UpdateLog(synxml_OnUpdateLog);
        }

        public EtlDispatcher(IList<StationObject> lstStation)
            : this()
        {
            lstStaObj = lstStation;
        }

        void synxml_OnUpdateLog(string StationID, string StationName, string TaskID, DispatchProcess dpStatus, bool IsUpdated)
        {
            if (IsUpdated)
            {
                log.FireTaskProcess(StationID,
                    TaskID,
                   dpStatus,
                    string.Format("{0}\t加油站 {1} 的 {2} 任务执行成功...", DateTime.Now, StationName, TaskID),
                    LogType.INFO);
            }
            else
            {
                //写日志文件
                log.FireTaskProcess(StationID,
                    TaskID,
                    dpStatus,
                    string.Format("{0}\t加油站 {1} 的 {2} 任务执行失败...", DateTime.Now, StationName, TaskID),
                    LogType.WARING);
            }
        }

        #region IEDTDispatcher 成员

        public void Initialize(IList<StationObject> lstStationObject)
        {
            lstStaObj = lstStationObject;
            //加载状态
            //LoadStatus();

            int TCount = Environment.ProcessorCount * 8;
            //根据当前机器的CPU个数设置适当的线程数
            ThreadPool.SetMaxThreads(TCount, TCount);
            ThreadPool.SetMinThreads(100, 100);

            TaskContinue();
            //监视时间程序
            //timeMonitorTimer = new Timer(new TimerCallback(WatchTime), lstStaObj, 1000 * 60, 1000 * 60);
            KillTimer = new Timer(new TimerCallback(KillDeathThread), lstStaObj, 1000 * 60, 1000 * 60 * 5);
        }

        public bool LoadStatus()
        {
            IList<StationStatus> lstso = DeSerialFromFile();
            if (lstso != null)
            {
                foreach (var station in lstso)
                {
                    foreach (var task in station.TaskList)
                    {
                        try
                        {
                            var tmptask = lstStaObj.Where(x => x.Station.StationID == station.StationID).First().StationTaskQueue.lstTaskObject.Where(x => x.TaskID == task.TaskID).First();
                            tmptask.ParamType = task.ParamType;
                            tmptask.Executions = task.Executions;
                            for (int i = 0; i < task.TaskQueue.Count; i++)
                            {
                                tmptask.Queue4PreDay.Enqueue(task.TaskQueue.ElementAt(i));
                            }
                        }
                        catch { }
                    }
                }
            }
            return true;
        }

        public bool Stop()
        {
            //timeMonitorTimer.Dispose();
            KillTimer.Dispose();

            return SaveStatus();
        }

        public void Run()
        {
            int staionCount = lstStaObj.Count;
            //计算任务优先级为以后优化调度算法做准备
            foreach (var so in lstStaObj)
            {
                int p = so.StationTaskQueue.Count;
                int hasparams = 0;
                int noparams = 0;
                foreach (var t in so.StationTaskQueue.lstTaskObject)
                {
                    if (t.HasParams)
                        hasparams++;
                    else
                        noparams++;
                }
                double jiaquan = hasparams * 2.9 + noparams * 1.4;
                int sita = (int)(jiaquan / Math.PI * 180);
                double li = p * Math.Cos(sita);
                double ll = p * Math.Sin(sita);
                uint priority = (uint)Math.Sqrt(li * li + ll * ll);
                so.Station.Priority = priority;
            }

            var sorted = from s in lstStaObj
                         orderby s.Station.Priority ascending
                         select s;
            IList<StationObject> sortedStation = sorted.ToList();
            foreach (var so in sortedStation)
            {
                if (so.Station.IsActive)
                    QueueTask(so);
            }
        }

        #endregion
        #region 私有方法
        /// <summary>
        /// 任务排队
        /// </summary>
        /// <param name="station"></param>
        private void QueueTask(StationObject station)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(PrepareRun), station);
            log.FireTaskProcess(station.Station.StationID, "0",
                DispatchProcess.WAIT,
                string.Format("{0}\t加油站 {1} 进入调度队列，等待被调度...", DateTime.Now, station.Station.StationName),
                LogType.INFO);
        }
        /// <summary>
        /// 准备运行任务
        /// </summary>
        /// <param name="obj">加油站对象</param>
        private void PrepareRun(object obj)
        {
            StationObject staobj = obj as StationObject;
            Random rand = new Random((int)DateTime.Now.Ticks);
            int interval = (int)staobj.Station.Interval;
#if DEBUG
            interval = rand.Next(interval - interval / 5, interval);
            staobj.TaskEvent.WaitOne(interval * 1000);
#else
                interval = interval * 60;
                interval = rand.Next(interval - interval / 10, interval);
                staobj.TaskEvent.WaitOne(interval * 1000);
#endif
            log.FireTaskProcess(staobj.Station.StationID, "0",
                DispatchProcess.READY,
                string.Format("================{0} 准备第{1}次调度==================", 
                staobj.Station.StationName, 
                staobj.CallTimes),
                LogType.INFO);
            if (Active)
                try
                {
                    staobj.BeginTime = DateTime.Now;
                    staobj.Station.ThreadInfo = null;
                    staobj.CallTimes++;

                    StartWork(staobj);
                }
                catch (System.Exception ex)
                {
                    log.FireTaskProcess(staobj.Station.StationID,
                        "0",
                        DispatchProcess.FAIL,
                        string.Format("ERROR:调度加油站 {0} 任务，出现:{1}", staobj.Station.StationName, ex.ToString()),
                        LogType.ERROR);
                }

            //扫行完一次任务，再次把自己加入线程队列
            if (Active)
                QueueTask(staobj);
        }

        /// <summary>
        /// 监视时间变化
        /// </summary>
        /// <param name="obj">加油站列表</param>
        private void WatchTime(object obj)
        {
            IList<StationObject> lst = obj as IList<StationObject>;
            if (DateTime.Now.Hour == EtlGlobal.BeginChek && DateTime.Now.Minute == 0)
            {
                ThreadPool.RegisterWaitForSingleObject(arEvent, new WaitOrTimerCallback(Update4PerDay), obj, new TimeSpan(0, EtlGlobal.DelayUpdate, 0), true);
                TaskPause();
                foreach (var staobj in lst)
                {
                    foreach (var taskobj in staobj.StationTaskQueue.lstTaskObject)
                    {
                        if (!Active)
                            return;
                        lock (taskobj)
                        {
                            //设置任务执行次数为0
                            taskobj.Executions = 0;
                        }
                    }
                }
            }
            if (loopCount++ % 10 == 0)
                SaveStatus();
        }
        /// <summary>
        /// 更新前一天的数据
        /// </summary>
        /// <param name="obj">加油站列表</param>
        private void Update4PerDay(object obj, bool timedOut)
        {
            log.WriteLog("0", "0", string.Format("{0} 全天更新开始.", DateTime.Now.ToString()), LogType.ERROR);
            IList<StationObject> lst = obj as IList<StationObject>;
            foreach (var staobj in lst)
            {
                string strip = GetInterBaseIP(staobj.Station.InterBaseIP);
                if (!string.IsNullOrEmpty(strip))
                {
                    if (!IsHostActived(strip))
                        continue;
                }
                else
                    continue;
                //取队列里元素的最大值，该值决定有多少数据没有更新
                int maxcount = staobj.StationTaskQueue.lstTaskObject.Max(x => x.Queue4PreDay.Count) - 1;
                while (maxcount > 0)
                {
                    foreach (var taskobj in staobj.StationTaskQueue.lstTaskObject)
                    {
                        if (!Active)
                            return;
                        if (taskobj.Queue4PreDay.Count >= 2)
                        {
                            IEtlInterface handler = new CETLHandler();
                            TaskObject temptask;
                            lock (taskobj)
                            {
                                temptask = taskobj.Clone() as TaskObject;
                            }
                            temptask.Action = SQLAction.UPDATE;
                            handler.log = log;
                            handler.Task = temptask;
                            temptask.ParamsStart = temptask.Queue4PreDay.ElementAt(1);
                            temptask.ParamsEnd = temptask.Queue4PreDay.ElementAt(0);
                            handler.DataExtract = GetExtratcter(staobj.Station, temptask);
                            handler.DataLoad = GetLoader(staobj.Station, temptask);
                            bool bSuccessed = handler.Execute(staobj.Station.StationID);
                            if (bSuccessed)
                                lock (taskobj)
                                {
                                    taskobj.Queue4PreDay.Dequeue();
                                }
                        }
                    }
                    maxcount--;
                }
            }
            log.WriteLog("0", "0", string.Format("{0} 全天更新完毕.", DateTime.Now.ToString()), LogType.ERROR);
            Environment.Exit(0);
            TaskContinue();
        }
        /// <summary>
        /// 抽取加载数据操作
        /// </summary>
        /// <param name="so">加油站对象</param>
        private void StartWork(StationObject so)
        {
            TaskWait();
            so.Station.ThreadInfo = Thread.CurrentThread;
            so.Station.ThreadInfo.Name = so.Station.StationID;

            if (!EtlGlobal.AllowStation.Equals("All", StringComparison.InvariantCultureIgnoreCase))
            {
                var lstTaskid = EtlGlobal.AllowStation.Split(new char[','], StringSplitOptions.RemoveEmptyEntries).Select(s => s.ToLower());
                if (!lstTaskid.Contains(so.Station.StationID.ToLower()))
                    return;
            }
            log.ConnectString = so.Station.DestIP;
            //判断主机是否存在
            string strip = GetInterBaseIP(so.Station.InterBaseIP);
            if (!string.IsNullOrEmpty(strip))
            {
                if (!IsHostActived(strip))
                {
                    log.FireTaskProcess(so.Station.StationID, "0", DispatchProcess.NOHOST,
                        string.Format("{0}：找不到对应该的主机.", so.Station.StationName),
                        LogType.ERROR);
                    return;
                }
            }
            else
            {
                log.FireTaskProcess(so.Station.StationID, "0", DispatchProcess.NOHOST,
                    string.Format("{0}：解析主机的地址出错，请检查配置文件。", so.Station.StationName),
                    LogType.ERROR);
                return;
            }
            

            //开工
            for (int i = 0; i < so.StationTaskQueue.lstTaskObject.Count; i++)
            {
                if (!Active)
                    return;
                TaskObject task = so.StationTaskQueue.lstTaskObject[i];
                if (!EtlGlobal.AllowTask.Equals("All", StringComparison.InvariantCultureIgnoreCase))
                {
                    var lstTaskid = EtlGlobal.AllowTask.Split(new char[','], StringSplitOptions.RemoveEmptyEntries).Select(s=>s.ToLower());
                    if (!lstTaskid.Contains(task.TaskID.ToString().ToLower()))
                        continue;
                }
                //对没有参数的整表更新,每x次调用只调用一次
                if (!task.HasParams && task.Action == SQLAction.DELADD)
                {
                    if (so.CallTimes % EtlGlobal.DelAddRate != 0)
                        continue;
                }
                //更新操作 ,每x次调用只调用一次
                if (!task.HasParams && task.Action == SQLAction.UPDATE)
                {
                    if (so.CallTimes % EtlGlobal.UpdateRate != 0)
                        continue;
                }
                log.FireTaskProcess(so.Station.StationID,
                    task.TaskID.ToString(),
                    DispatchProcess.EXCUTE,
                    string.Format("{0}\t正在调度 {1} 的 {2}任务...", DateTime.Now, so.Station.StationName, task.TaskID),
                    LogType.INFO);
                IEtlInterface handler = new CETLHandler();
                handler.log = log;
                handler.Task = task;
                handler.DataExtract = GetExtratcter(so.Station, task);
                handler.DataLoad = GetLoader(so.Station, task);

                switch (task.ParamType)
                {
                    //时间步进的处理
                    case StepType.DATETIME:
                        try
                        {
                            DateTime DbTime = handler.DataExtract.GetDBTime();
                            DateTime EndTime = DateTime.Parse(GetEndFromXML(so.Station.StationID, task.TaskID.ToString()));
                            //结束时间 大于 数据库当前时间-30分钟
                            if (EndTime >= DbTime.AddMinutes(-task.Step))
                            {
                                log.FireTaskProcess(so.Station.StationID,
                                    task.TaskID.ToString(),
                                    DispatchProcess.STOP,
                                    string.Format("{0}\t{1} 的 {2}数据库时间小于最后调度时间 停止调度...", DateTime.Now, so.Station.StationName, task.TaskID),
                                    LogType.WARING);
                                continue;
                            }
                        }
                        catch (Exception ex)
                        {

                            log.FireTaskProcess(so.Station.StationID,
                                task.TaskID.ToString(),
                                DispatchProcess.STOP,
                                string.Format("{0}\t{1} 的 {2} DATETIME执行期间出现：{3} 停止调度...", DateTime.Now, so.Station.StationName, task.TaskID, ex.Message),
                                LogType.ERROR);
                            continue;
                        }
                        break;
                    //ID步进的处理
                    case StepType.INT:
                        try
                        {
                            int maxid = handler.DataExtract.GetMaxID(task.TaskName, task.PrimaryKeys[1]);
                            task.MaxID = maxid;
                            int StepStart = int.Parse(GetStartFromXML(so.Station.StationID, task.TaskID.ToString()));
                            //开始ID大于最大ID 停止调度
                            if (StepStart >= maxid)
                            {
                                log.FireTaskProcess(so.Station.StationID,
                                    task.TaskID.ToString(),
                                    DispatchProcess.STOP,
                                    string.Format("{0}\t{1} 的 {2}数据库MAXID小于最后调度ID 停止调度...", DateTime.Now, so.Station.StationName, task.TaskID),
                                    LogType.WARING);
                                continue;
                            }
                        }
                        catch (Exception ex)
                        {
                            log.FireTaskProcess(so.Station.StationID,
                                task.TaskID.ToString(),
                                DispatchProcess.STOP,
                                string.Format("{0}\t{1} 的 {2} INT执行期间出现：{3} 停止调度...", DateTime.Now, so.Station.StationName, task.TaskID, ex.Message),
                                LogType.ERROR);
                            continue;
                        }
                        break;
                }

                task.HandlBeginTime = DateTime.Now;
                bool bSuccessed = handler.Execute(so.Station.StationID);
                ////为每日重抽数据做准备
                //lock (task)
                //{
                //    if (task.Executions == 0 && task.HasParams)
                //    {
                //        task.Queue4PreDay.Enqueue(task.ParamsStart);
                //        Debug.WriteLine(string.Format("----{0} {1} {2} enqueued...", so.Station.StationID, task.TaskID, task.ParamsStart));
                //    }
                //    task.Executions++;
                //}
                task.HandlEndTime = DateTime.Now;
                if (bSuccessed)
                {
                    try
                    {
                        task.DBTime = handler.DataExtract.GetDBTime();
                        task.ResultMaxID = handler.DataExtract.GetMaxID(EtlGlobal.DT_MAXID, task.PrimaryKeys[1]);
                    }
                    catch (System.Exception ex)
                    {
                        log.FireTaskProcess(so.Station.StationID,
                            task.TaskID.ToString(),
                            DispatchProcess.COMPLETEDERROR,
                            string.Format("{0}\t加油站 {1} 的 {2} 任务执行成功,但取数据库时间发生错误。用本地时间代替数据库时间。 {3}", DateTime.Now, so.Station.StationName, task.TaskID, ex.Message),
                            LogType.ERROR);
                        task.DBTime = DateTime.Now;
                    }
                }
                UpdateSQLParam(bSuccessed, so.Station, task);
            }
        }
        /// <summary>
        /// 取开始标志值
        /// </summary>
        /// <param name="StationID">加油站ID</param>
        /// <param name="TaskID">任务ID</param>
        /// <returns>值</returns>
        private string GetStartFromXML(string StationID, string TaskID)
        {
            return synxml.GetStartFromXML(StationID, TaskID);
        }
        /// <summary>
        /// 取结束标志值
        /// </summary>
        /// <param name="StationID">加油站ID</param>
        /// <param name="TaskID">任务ID</param>
        /// <returns>值</returns>
        private string GetEndFromXML(string StationID, string TaskID)
        {
            return synxml.GetEndFromXML(StationID, TaskID);
        }
        /// <summary>
        /// 更新任务时间配置
        /// </summary>
        /// <param name="IsSucceed">任务是否执行成功</param>
        /// <param name="stationRule">加油站信息</param>
        /// <param name="task">任务信息</param>
        private void UpdateSQLParam(bool IsSucceed, StationInfo station, TaskObject task)
        {
            try
            {
                synxml.UpdateSQLParam(IsSucceed, station, task);
            }
            catch (System.Exception ex)
            {
                log.FireTaskProcess(station.StationID,
                            task.TaskID.ToString(),
                            DispatchProcess.COMPLETEDERROR,
                            string.Format("ERROR:{0} {1}  {2} 更新XML发生异常 {3}", DateTime.Now, station.StationName, task.TaskID, ex.Message),
                            LogType.ERROR);
            }

        }
        /// <summary>
        /// 获取加载器
        /// </summary>
        /// <param name="station">加油站对象</param>
        /// <param name="task">任务对象</param>
        /// <returns>返回加载接口</returns>
        private ILoader GetLoader(StationInfo station, TaskObject task)
        {
            EtlDataFactory etlFactory = new EtlDataFactory();
            ILoader loader = null;
            switch (task.DstDS)
            {
                case DataSource.IB:
                    loader = etlFactory.CreateLoader<CIBDataFactory>();
                    break;
                case DataSource.MYSQL:
                    loader = etlFactory.CreateLoader<CMySQLDataFactory>();
                    break;
                case DataSource.MSSQL:
                    loader = etlFactory.CreateLoader<CSQLDataFactory>();
                    break;
                default:
                    break;
            }
            loader.ip = station.DestIP;
            return loader;
        }
        /// <summary>
        /// 获取抽取器
        /// </summary>
        /// <param name="station">加油站对象</param>
        /// <param name="task">任务对象</param>
        /// <returns>返回抽取接口</returns>
        private IExtracter GetExtratcter(StationInfo station, TaskObject task)
        {
            EtlDataFactory etlFactory = new EtlDataFactory();
            IExtracter etxracter = null;
            switch (task.SrcDS)
            {
                case DataSource.IB:
                    etxracter = etlFactory.CreateExtrater<CIBDataFactory>();
                    etxracter.ip = station.InterBaseIP;
                    break;
                case DataSource.MYSQL:
                    etxracter = etlFactory.CreateExtrater<CMySQLDataFactory>();
                    etxracter.ip = station.MySQLIP;
                    break;
                case DataSource.MSSQL:
                    etxracter = etlFactory.CreateExtrater<CSQLDataFactory>();
                    etxracter.ip = station.MSSQLIP;
                    break;
                default:
                    break;
            }
            return etxracter;
        }
        /// <summary>
        /// 解析IB数据库连接串的IP
        /// </summary>
        /// <param name="ibconnect">连接串</param>
        /// <returns>IP地址</returns>
        private string GetInterBaseIP(string ibconnect)
        {
            Match m = Regex.Match(ibconnect, @"(?<Database>[0-9]*[.][0-9]*[.][0-9]*[.][0-9]*)");
            return m.Success == true ? m.Groups["Database"].Value : "";
        }
        /// <summary>
        /// 判断主机是否存在
        /// </summary>
        /// <returns>存在返回true</returns>
        private bool IsHostActived(string stationip)
        {
            try
            {
                using (Ping p = new Ping())
                {
                    return IPStatus.Success == p.Send(stationip).Status;
                }
            }
            catch (System.Exception ex)
            {
                log.WriteLog(ex.Message);
                return false;
            }

        }

        /// <summary>
        /// 保存任务状态
        /// </summary>
        /// <returns>成功返回True</returns>
        private bool SaveStatus()
        {
            return true;
            Debug.Assert(lstStaObj != null);
            IList<StationStatus> lstStationStatus = new List<StationStatus>();
            foreach (var s in lstStaObj)
            {
                StationStatus ss = new StationStatus();
                ss.StationID = s.Station.StationID;
                ss.TaskList = new List<TaskStatus>();
                foreach (var t in s.StationTaskQueue.lstTaskObject)
                {
                    TaskStatus ts = new TaskStatus();
                    ts.TaskID = t.TaskID;
                    ts.ParamType = t.ParamType;
                    ts.TaskQueue = new Queue<object>();
                    ts.Executions = t.Executions;
                    lock (t)
                    {
                        for (int idx = 0; idx < t.Queue4PreDay.Count; idx++)
                        {
                            ts.TaskQueue.Enqueue(t.Queue4PreDay.ElementAt(idx));
                        }
                    }
                    ss.TaskList.Add(ts);
                }
                lstStationStatus.Add(ss);
            }
            try
            {
                File.Delete("Stations.dat");
                using (FileStream fs = new FileStream("Stations.dat", FileMode.Create, FileAccess.ReadWrite))
                {
                    IFormatter formatter = new BinaryFormatter();
                    formatter.Serialize(fs, lstStationStatus);
                    fs.Flush();
                    //fs.Close();
                }
            }
            catch (System.Exception ex)
            {
                log.FireTaskProcess("", "",
                            DispatchProcess.FAIL,
                            string.Format("ERROR:SaveStatus 方法异常: {0}", ex.ToString()),
                            LogType.ERROR);
                return false;
            }

            return true;
        }
        /// <summary>
        /// 反序列化加油站状态列表
        /// </summary>
        /// <returns>成功返回状态列表，失败返回null</returns>
        private IList<StationStatus> DeSerialFromFile()
        {
            if (!File.Exists("Stations.dat"))
                return null;
            try
            {
                IList<StationStatus> lstso;
                using (FileStream fs = new FileStream("Stations.dat", FileMode.Open, FileAccess.Read))
                {
                    IFormatter formatter = new BinaryFormatter();
                    lstso = (IList<StationStatus>)formatter.Deserialize(fs);
                    //fs.Close();
                }
                return lstso;
            }
            catch (System.Exception ex)
            {
                log.FireTaskProcess("", "",
                            DispatchProcess.FAIL,
                            string.Format("ERROR:DeSerialFromFile方法异常: {0}", ex.ToString()),
                            LogType.ERROR);
                return null;
            }
        }


        //检查杀死 卡死的线程
        private void KillDeathThread(object obj)
        {
            IList<StationObject> lstso = obj as IList<StationObject>;
            int workerThreads, completionPortThreads, workerThreads1, completionPortThreads1;
            ThreadPool.GetMaxThreads(out workerThreads, out completionPortThreads);
            ThreadPool.GetAvailableThreads(out workerThreads1, out completionPortThreads1);
            int runThreads = workerThreads - workerThreads1;
            log.WriteLog(string.Format("共有 {0} 个加油站，线程池中有 {1} 个线程正在运行...", lstso.Count, runThreads));
            foreach (var station in lstso)
            {
                TimeSpan ts = DateTime.Now - station.BeginTime;
                if (ts.TotalMinutes >= EtlGlobal.MaxExecuteTimeOut)
                {
                    if (Active)
                    {
                        if (station.Station.ThreadInfo == null)
                            continue;
                        try
                        {
                            Debug.WriteLine("Abort thread:" + station.Station.ThreadInfo.Name);
                            station.Station.ThreadInfo.Abort();
                        }
                        catch { }
                        QueueTask(station);
                    }
                }
            }
        }

        private void TaskPause()
        {
            log.WriteLog("TaskPause...");
            mrEvent.Reset();
        }

        private void TaskWait()
        {
            log.WriteLog("TaskWait...");
            mrEvent.WaitOne();
        }

        private void TaskContinue()
        {
            log.WriteLog("TaskContinue...");
            mrEvent.Set();
        }
        #endregion
    }
}
